#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "directorio.h"
#include "fuse.h"
#include "fat32.h"
#include "direccionamiento.h"
#include <pthread.h>

#include "lib_planificador.h"



#define new_instance(x) ((x*) malloc(sizeof(x)))
unsigned int SECTOR_PER_CLUSTER;
unsigned int *entrada_FAT;
struct boot_sector_values* v_boot_sector;
struct FS_information_sector_values * v_FS_information_sector;
FILE *fp;


static const char *hello_str = "Hello World!\n";
static const char *hello_path = "/algo.txt";

static int sistematicos_getattr(const char *path, struct stat *stbuf)
{
    /*int res = 0;
    printf("Entro al GetAttr con path %s\n", path);
    if(strcmp(path, "/") != 0)
    {
		ENTRADA83 * entrada;
		entrada = obtener_entrada_para(path);
		if (entrada != NULL)
		{
			free(entrada);
			entrada = NULL;
		}
    }
    memset(stbuf, 0, sizeof(struct stat));
    if(strcmp(path, "/") == 0 || strcmp(path, "/testeo") == 0) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
    }
    else if(strcmp(path, hello_path) == 0 || strcmp(path, "/hola.txt") == 0) {
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = strlen(hello_str);
    }
    else
        res = -ENOENT;

    return res;*/


	printf("\nEntro al GetAttr con path %s\n", path);
    int res = 0;
    memset(stbuf, 0, sizeof(struct stat));

    if (strcmp(path,"/")==0)
    {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
        return res;
    }

    ENTRADA83 * entrada;
    //if(strcmp(path, "/") == 0 || strcmp(path, "/testeo") == 0) {
    entrada = obtener_entrada_para(path);
    //printf("El atributo es: %x\n",entrada->atributos);
    if (entrada == NULL) {
    	res = -ENOENT;
        free(entrada);
        entrada = NULL;
    	printf("Salgo del GetAttrib en 1\n");
    	return res;
    }
    else if(entrada->atributos == 0x10) {
    //else if(strcmp(path, "/testeo") == 0) {
    	printf("Es un directorio\n");
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
    }
    //else if(strcmp(path, hello_path) == 0 || strcmp(path, "/hola.txt") == 0) {
    else if(entrada->atributos == 0x20){
    	printf("Es un archivo\n");
        stbuf->st_mode = S_IFREG | 0777;
        stbuf->st_nlink = 1;
        //stbuf->st_size = strlen(hello_str);
        stbuf->st_size = entrada->tamanio;
    }
    else if(entrada->atributos == 0x21){
        	printf("Es un archivo ReadOnly!!!!\n");
            stbuf->st_mode = S_IFREG | 0444;
            stbuf->st_nlink = 1;
            //stbuf->st_size = strlen(hello_str);
            stbuf->st_size = entrada->tamanio;
        }
    else
    {
    	printf("No sirve para nada\n");
    	res = -ENOENT;
    }
    free(entrada);
    entrada = NULL;
    printf("Salgo del GetAttrib en 2\n");

    return res;

}


static int sistematicos_open(const char *path, struct fuse_file_info *fi)
{
    //if(strcmp(path, hello_path) != 0)
      //  return -ENOENT;

    if((fi->flags & 3) != O_RDONLY)
        return -EACCES;

    return 0;
}

static int sistematicos_read(const char *path, char *buf, size_t size, off_t offset,struct fuse_file_info *fi)
{
    size_t len;
    (void) fi;

    ENTRADA83 * entrada;
    SUPER_CACHO bloque;
    entrada = obtener_entrada_para(path);
    //printf("El atributo es: %x\n",entrada->atributos);
    if (entrada == NULL)
    {
     	printf("Salgo del read por que no existe la entrada\n");
     	return -ENOENT;
    }
    len = entrada->tamanio;
    free(entrada);entrada = NULL;
    if (offset < len) {
        if (offset + size > len)
            size = len - offset;
		//cacho_de_memoria = FAT_traer_informacion_encadenada(2,largo_entrada);
		bloque = FAT_traer_contenido_de_directorio(path);
        memcpy(buf, bloque.cacho_de_memoria + offset, size);
        free(bloque.cacho_de_memoria);bloque.cacho_de_memoria = NULL;
    } else
        size = 0;

    return size;
}
static int sistematicos_mkdir(const char *path, mode_t mode)
{
	int res;
	res = 0;

	printf("\nEl path es %s\n",path);


	return -ENOENT;
}
static int sistematicos_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                         off_t offset, struct fuse_file_info *fi)
{
    (void) offset;
    (void) fi;

    SUPER_CACHO bloque;
    //cacho_de_memoria = FAT_traer_informacion_encadenada(2,largo_entrada);
    printf("\nEntro al REadDir con path %s", path);
    bloque = FAT_traer_contenido_de_directorio(path);
    /*if(cacho_de_memoria == NULL)
  	  {
    	return -ENOENT;
  	  }*/
    //printf ("\nEl largo total del cacho de memoria es %d\n", *largo_entrada *  SIZE_SECTOR * SECTOR_PER_CLUSTER);

    ENTRADA83 *entrada;
    //printf("\nListo la entrada del direcotrio RAIZ");
    //Listamos la entrada del raíz por pantalla
    entrada = malloc(sizeof(ENTRADA83));
    if (strcmp(path,"/")==0)
    {
		filler(buf, ".", NULL, 0);
		printf("\n.");
		filler(buf, "..", NULL, 0);
		printf("\n..\n");
    }
    //filler(buf,"algo.txt",NULL,0);
    //printf("\nlleno con algo.txt");
    memcpy(entrada,bloque.cacho_de_memoria,sizeof(ENTRADA83));
    int count;
    count = 1;
    while (entrada->nombre[0] != 0x00)
    {
  	 //char x =  new_instance(int);
    	if (entrada->atributos != ATR_NOM_LARGO)
    	{
    		char nombre[12 + 1];
    		FAT_armar_nombre_corto(entrada->nombre, nombre);
    		printf("Nombre Corto: %s\n",nombre);
    		filler(buf, nombre , NULL, 0);
    	}

    	else
    	{
    		char nombre[13 + 1];

    		FAT_armar_parte_de_nombre((ENTRADA_LARGA*) entrada, nombre);
    		printf("Nombre Largo: %s\n",nombre);
    		filler(buf, nombre, NULL, 0);
    		count++;

    	}
    	//Vuelvo a leer otra entrada
    	free(entrada);
    	entrada = NULL;
    	entrada = malloc(sizeof(ENTRADA83));
    	memcpy(entrada,bloque.cacho_de_memoria+count*sizeof(ENTRADA83),sizeof(ENTRADA83));
    	count++;
    }
	free(entrada);
	entrada = NULL;
    free(bloque.cacho_de_memoria);
    bloque.cacho_de_memoria = NULL;
    printf("\nFree a cacho de memoria\n");
    return 0;
}

static struct fuse_operations hello_oper = {
    .getattr	= sistematicos_getattr,
    .readdir	= sistematicos_readdir,
    .open	= sistematicos_open,
    .read	= sistematicos_read,
    .mkdir = sistematicos_mkdir,
};

int main(int argc, char *argv[])
{

  char * sector;
  //Asigno espacio en memoria dinámica
  v_boot_sector = malloc(512);
  v_FS_information_sector = malloc(512);

  //Abro el archivo FAT32
  if((fp = fopen(".//fat32.disk", "r+")) == NULL){
	printf("Imposible de abrir el archivo.\n");
	exit(1);
  }

  //Traer el primer y segundo sector del disco. El primero es el boot sector y el segundo es el FS Information

  memcpy(v_boot_sector,sector = leer_sector(0, fp),512);
  free(sector);
  sector = NULL;
  memcpy(v_FS_information_sector,sector = leer_sector(1, fp),512);
  free(sector);
  sector = NULL;
  printf("\nBytes por sector: %d", (*v_boot_sector).value_bytes_per_sector);
  printf("\nsectores FAT: %d", (*v_boot_sector).value_sectors_per_fat_table);

  //Asigno cuantos sectores por cluster maneja el disco
  SECTOR_PER_CLUSTER = (*v_boot_sector).value_sector_per_cluster;
  dcc_calcular_offset_data_region(*v_boot_sector);

  //Traigo la tabla FAT a memoria :D
  entrada_FAT = FAT_llenar_Tabla_FAT (*v_boot_sector, fp);

  //TEST: Leo la primer entrada de directorio :O

  //printf("\nEl numero de cluster para la entrada testeo es: %d", FAT_obtener_cluster_inicial_para(cacho_de_memoria, *largo_entrada *  SIZE_SECTOR * SECTOR_PER_CLUSTER, "testeo"));
  //printf ("\nTerminó con count en %d", count);
  //printf("\nSarglanga says %s", obtener_archivo_de_path("/home/test.txt"));
  return fuse_main(argc, argv, &hello_oper);
}

